const path = require("path");
const fs = require("fs-extra");
const yaml = require("js-yaml");
const chalk = require("chalk");
const inquirer = require("inquirer");
const fileManager = require("./file-manager");
const configLoader = require("./config-loader");
const { extractYamlFromAgent } = require("../../lib/yaml-utils");
const BaseIdeSetup = require("./ide-base-setup");
const resourceLocator = require("./resource-locator");

class IdeSetup extends BaseIdeSetup {
    constructor() {
        super();
        this.ideAgentConfig = null;
    }

    async loadIdeAgentConfig() {
        if (this.ideAgentConfig) return this.ideAgentConfig;

        try {
            const configPath = path.join(
                __dirname,
                "..",
                "config",
                "ide-agent-config.yaml"
            );
            const configContent = await fs.readFile(configPath, "utf8");
            this.ideAgentConfig = yaml.load(configContent);
            return this.ideAgentConfig;
        } catch (error) {
            console.warn("加载 IDE 智能体配置失败，使用默认配置");
            return {
                "roo-permissions": {},
                "cline-order": {},
            };
        }
    }

    async setup(
        ide,
        installDir,
        selectedAgent = null,
        spinner = null,
        preConfiguredSettings = null
    ) {
        const ideConfig = await configLoader.getIdeConfiguration(ide);

        if (!ideConfig) {
            console.log(chalk.yellow(`\nIDE ${ide} 暂不支持`));
            return false;
        }

        switch (ide) {
            case "cursor":
                return this.setupCursor(installDir, selectedAgent);
            case "claude-code":
                return this.setupClaudeCode(installDir, selectedAgent);
            case "windsurf":
                return this.setupWindsurf(installDir, selectedAgent);
            case "trae":
                return this.setupTrae(installDir, selectedAgent);
            case "roo":
                return this.setupRoo(installDir, selectedAgent);
            case "cline":
                return this.setupCline(installDir, selectedAgent);
            case "gemini":
                return this.setupGeminiCli(installDir, selectedAgent);
            case "github-copilot":
                return this.setupGitHubCopilot(
                    installDir,
                    selectedAgent,
                    spinner,
                    preConfiguredSettings
                );
            default:
                console.log(chalk.yellow(`\nIDE ${ide} 暂不支持`));
                return false;
        }
    }

    async setupCursor(installDir, selectedAgent) {
        const cursorRulesDir = path.join(installDir, ".cursor", "rules");
        const agents = selectedAgent
            ? [selectedAgent]
            : await this.getAllAgentIds(installDir);

        await fileManager.ensureDirectory(cursorRulesDir);

        for (const agentId of agents) {
            const agentPath = await this.findAgentPath(agentId, installDir);

            if (agentPath) {
                const mdcContent = await this.createAgentRuleContent(
                    agentId,
                    agentPath,
                    installDir,
                    "mdc"
                );
                const mdcPath = path.join(cursorRulesDir, `${agentId}.mdc`);
                await fileManager.writeFile(mdcPath, mdcContent);
                console.log(chalk.green(`✓ 已创建规则: ${agentId}.mdc`));
            }
        }

        console.log(chalk.green(`\n✓ 已创建 Cursor 规则在 ${cursorRulesDir}`));
        return true;
    }

    async setupClaudeCode(installDir, selectedAgent) {
        // Setup sdat-core commands
        const coreSlashPrefix = await this.getCoreSlashPrefix(installDir);
        const coreAgents = selectedAgent
            ? [selectedAgent]
            : await this.getCoreAgentIds(installDir);
        const coreTasks = await this.getCoreTaskIds(installDir);
        await this.setupClaudeCodeForPackage(
            installDir,
            "core",
            coreSlashPrefix,
            coreAgents,
            coreTasks,
            ".sdat-core"
        );

        // Setup expansion pack commands
        const expansionPacks =
            await this.getInstalledExpansionPacks(installDir);
        for (const packInfo of expansionPacks) {
            const packSlashPrefix = await this.getExpansionPackSlashPrefix(
                packInfo.path
            );
            const packAgents = await this.getExpansionPackAgents(packInfo.path);
            const packTasks = await this.getExpansionPackTasks(packInfo.path);

            if (packAgents.length > 0 || packTasks.length > 0) {
                // Use the actual directory name where the expansion pack is installed
                const rootPath = path.relative(installDir, packInfo.path);
                await this.setupClaudeCodeForPackage(
                    installDir,
                    packInfo.name,
                    packSlashPrefix,
                    packAgents,
                    packTasks,
                    rootPath
                );
            }
        }

        return true;
    }

    async setupClaudeCodeForPackage(
        installDir,
        packageName,
        slashPrefix,
        agentIds,
        taskIds,
        rootPath
    ) {
        const commandsBaseDir = path.join(
            installDir,
            ".claude",
            "commands",
            slashPrefix
        );
        const agentsDir = path.join(commandsBaseDir, "agents");
        const tasksDir = path.join(commandsBaseDir, "tasks");

        // Ensure directories exist
        await fileManager.ensureDirectory(agentsDir);
        await fileManager.ensureDirectory(tasksDir);

        // Setup agents
        for (const agentId of agentIds) {
            // Find the agent file - for expansion packs, prefer the expansion pack version
            let agentPath;
            if (packageName !== "core") {
                // For expansion packs, first try to find the agent in the expansion pack directory
                const expansionPackPath = path.join(
                    installDir,
                    rootPath,
                    "agents",
                    `${agentId}.md`
                );
                if (await fileManager.pathExists(expansionPackPath)) {
                    agentPath = expansionPackPath;
                } else {
                    // Fall back to core if not found in expansion pack
                    agentPath = await this.findAgentPath(agentId, installDir);
                }
            } else {
                // For core, use the normal search
                agentPath = await this.findAgentPath(agentId, installDir);
            }

            const commandPath = path.join(agentsDir, `${agentId}.md`);

            if (agentPath) {
                // Create command file with agent content
                let agentContent = await fileManager.readFile(agentPath);

                // Replace {root} placeholder with the appropriate root path for this context
                agentContent = agentContent.replace(/{root}/g, rootPath);

                // Add command header
                let commandContent = `# /${agentId} Command\n\n`;
                commandContent += `当使用此命令时，请采用以下智能体角色：\n\n`;
                commandContent += agentContent;

                await fileManager.writeFile(commandPath, commandContent);
                console.log(chalk.green(`✓ 已创建智能体命令: /${agentId}`));
            }
        }

        // Setup tasks
        for (const taskId of taskIds) {
            // Find the task file - for expansion packs, prefer the expansion pack version
            let taskPath;
            if (packageName !== "core") {
                // For expansion packs, first try to find the task in the expansion pack directory
                const expansionPackPath = path.join(
                    installDir,
                    rootPath,
                    "tasks",
                    `${taskId}.md`
                );
                if (await fileManager.pathExists(expansionPackPath)) {
                    taskPath = expansionPackPath;
                } else {
                    // Fall back to core if not found in expansion pack
                    taskPath = await this.findTaskPath(taskId, installDir);
                }
            } else {
                // For core, use the normal search
                taskPath = await this.findTaskPath(taskId, installDir);
            }

            const commandPath = path.join(tasksDir, `${taskId}.md`);

            if (taskPath) {
                // Create command file with task content
                let taskContent = await fileManager.readFile(taskPath);

                // Replace {root} placeholder with the appropriate root path for this context
                taskContent = taskContent.replace(/{root}/g, rootPath);

                // Add command header
                let commandContent = `# /${taskId} Task\n\n`;
                commandContent += `当此命令被使用时，执行以下任务：\n\n`;
                commandContent += taskContent;

                await fileManager.writeFile(commandPath, commandContent);
                console.log(chalk.green(`✓ 已创建任务命令: /${taskId}`));
            }
        }

        console.log(
            chalk.green(
                `\n✓ 已创建 Claude Code 命令 ${packageName} 在 ${commandsBaseDir}`
            )
        );
        console.log(chalk.dim(`  - Agents in: ${agentsDir}`));
        console.log(chalk.dim(`  - Tasks in: ${tasksDir}`));
    }

    async setupWindsurf(installDir, selectedAgent) {
        const windsurfRulesDir = path.join(installDir, ".windsurf", "rules");
        const agents = selectedAgent
            ? [selectedAgent]
            : await this.getAllAgentIds(installDir);

        await fileManager.ensureDirectory(windsurfRulesDir);

        for (const agentId of agents) {
            // Find the agent file
            const agentPath = await this.findAgentPath(agentId, installDir);

            if (agentPath) {
                const agentContent = await fileManager.readFile(agentPath);
                const mdPath = path.join(windsurfRulesDir, `${agentId}.md`);

                // Create MD content (similar to Cursor but without frontmatter)
                let mdContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
                mdContent += `当用户输入 \`@${agentId}\` 时，激活 ${await this.getAgentTitle(
                    agentId,
                    installDir
                )} 智能体的角色定位。\n\n`;
                mdContent += "## Agent Activation\n\n";
                mdContent +=
                    "关键：阅读完整的 YAML 内容，开始激活以改变你的状态，遵循启动部分的说明，保持此状态直到收到退出此模式的指令：\n\n";
                mdContent += "```yaml\n";
                // Extract just the YAML content from the agent file
                const yamlContent = extractYamlFromAgent(agentContent);
                if (yamlContent) {
                    mdContent += yamlContent;
                } else {
                    // If no YAML found, include the whole content minus the header
                    mdContent += agentContent.replace(/^#.*$/m, "").trim();
                }
                mdContent += "\n```\n\n";
                mdContent += "## File Reference\n\n";
                const relativePath = path
                    .relative(installDir, agentPath)
                    .replace(/\\/g, "/");
                mdContent += `完整的智能体定义可在 [${relativePath}](${relativePath}) 中找到。\n\n`;
                mdContent += "## 用法\n\n";
                mdContent += `当用户输入 \`@${agentId}\` 时，激活 ${await this.getAgentTitle(
                    agentId,
                    installDir
                )} 角色，并遵循上述 YAML 配置中定义的所有指令。\n`;

                await fileManager.writeFile(mdPath, mdContent);
                console.log(
                    chalk.green(`✓ 已创建 Windsurf 规则: ${agentId}.md`)
                );
            }
        }

        console.log(
            chalk.green(`\n✓ 已创建 Windsurf 规则在 ${windsurfRulesDir}`)
        );

        return true;
    }

    async setupTrae(installDir, selectedAgent) {
        const traeRulesDir = path.join(installDir, ".trae", "rules");
        const agents = selectedAgent
            ? [selectedAgent]
            : await this.getAllAgentIds(installDir);

        await fileManager.ensureDirectory(traeRulesDir);

        for (const agentId of agents) {
            // Find the agent file
            const agentPath = await this.findAgentPath(agentId, installDir);

            if (agentPath) {
                const agentContent = await fileManager.readFile(agentPath);
                const mdPath = path.join(traeRulesDir, `${agentId}.md`);

                // Create MD content (similar to Cursor but without frontmatter)
                let mdContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
                mdContent += `当用户输入 \`@${agentId}\` 时，激活 ${await this.getAgentTitle(
                    agentId,
                    installDir
                )} 智能体角色。\n\n`;
                mdContent += "## Agent Activation\n\n";
                mdContent +=
                    "关键：阅读完整的 YAML，开始激活以改变你的状态，遵循启动部分的说明，保持此状态直到收到退出此模式的指令：\n\n";
                mdContent += "```yaml\n";
                // Extract just the YAML content from the agent file
                const yamlContent = extractYamlFromAgent(agentContent);
                if (yamlContent) {
                    mdContent += yamlContent;
                } else {
                    // If no YAML found, include the whole content minus the header
                    mdContent += agentContent.replace(/^#.*$/m, "").trim();
                }
                mdContent += "\n```\n\n";
                mdContent += "## File Reference\n\n";
                const relativePath = path
                    .relative(installDir, agentPath)
                    .replace(/\\/g, "/");
                mdContent += `完整的智能体定义可在 [${relativePath}](${relativePath}) 中找到。\n\n`;
                mdContent += "## Usage\n\n";
                mdContent += `当用户输入 \`@${agentId}\` 时，激活此 ${await this.getAgentTitle(
                    agentId,
                    installDir
                )} 角色，并遵循上述 YAML 配置中定义的所有指令。\n`;

                await fileManager.writeFile(mdPath, mdContent);
                console.log(chalk.green(`✓ Created rule: ${agentId}.md`));
            }
        }
    }

    async findAgentPath(agentId, installDir) {
        // Try to find the agent file in various locations
        const possiblePaths = [
            path.join(installDir, ".sdat-core", "agents", `${agentId}.md`),
            path.join(installDir, "agents", `${agentId}.md`),
        ];

        // Also check expansion pack directories
        const glob = require("glob");
        const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
        for (const expDir of expansionDirs) {
            possiblePaths.push(path.join(installDir, expDir, `${agentId}.md`));
        }

        for (const agentPath of possiblePaths) {
            if (await fileManager.pathExists(agentPath)) {
                return agentPath;
            }
        }

        return null;
    }

    async getAllAgentIds(installDir) {
        const glob = require("glob");
        const allAgentIds = [];

        // Check core agents in .sdat-core or root
        let agentsDir = path.join(installDir, ".sdat-core", "agents");
        if (!(await fileManager.pathExists(agentsDir))) {
            agentsDir = path.join(installDir, "agents");
        }

        if (await fileManager.pathExists(agentsDir)) {
            const agentFiles = glob.sync("*.md", { cwd: agentsDir });
            allAgentIds.push(
                ...agentFiles.map((file) => path.basename(file, ".md"))
            );
        }

        // Also check for expansion pack agents in dot folders
        const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
        for (const expDir of expansionDirs) {
            const fullExpDir = path.join(installDir, expDir);
            const expAgentFiles = glob.sync("*.md", { cwd: fullExpDir });
            allAgentIds.push(
                ...expAgentFiles.map((file) => path.basename(file, ".md"))
            );
        }

        // Remove duplicates
        return [...new Set(allAgentIds)];
    }

    async getCoreAgentIds(installDir) {
        const allAgentIds = [];

        // Check core agents in .sdat-core or root only
        let agentsDir = path.join(installDir, ".sdat-core", "agents");
        if (!(await fileManager.pathExists(agentsDir))) {
            agentsDir = path.join(installDir, "sdat-core", "agents");
        }

        if (await fileManager.pathExists(agentsDir)) {
            const glob = require("glob");
            const agentFiles = glob.sync("*.md", { cwd: agentsDir });
            allAgentIds.push(
                ...agentFiles.map((file) => path.basename(file, ".md"))
            );
        }

        return [...new Set(allAgentIds)];
    }

    async getCoreTaskIds(installDir) {
        const allTaskIds = [];

        // Check core tasks in .sdat-core or root only
        let tasksDir = path.join(installDir, ".sdat-core", "tasks");
        if (!(await fileManager.pathExists(tasksDir))) {
            tasksDir = path.join(installDir, "sdat-core", "tasks");
        }

        if (await fileManager.pathExists(tasksDir)) {
            const glob = require("glob");
            const taskFiles = glob.sync("*.md", { cwd: tasksDir });
            allTaskIds.push(
                ...taskFiles.map((file) => path.basename(file, ".md"))
            );
        }

        // Check common tasks
        const commonTasksDir = path.join(installDir, "common", "tasks");
        if (await fileManager.pathExists(commonTasksDir)) {
            const commonTaskFiles = glob.sync("*.md", { cwd: commonTasksDir });
            allTaskIds.push(
                ...commonTaskFiles.map((file) => path.basename(file, ".md"))
            );
        }

        return [...new Set(allTaskIds)];
    }

    async getAgentTitle(agentId, installDir) {
        // Try to find the agent file in various locations
        const possiblePaths = [
            path.join(installDir, ".sdat-core", "agents", `${agentId}.md`),
            path.join(installDir, "agents", `${agentId}.md`),
        ];

        // Also check expansion pack directories
        const glob = require("glob");
        const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
        for (const expDir of expansionDirs) {
            possiblePaths.push(path.join(installDir, expDir, `${agentId}.md`));
        }

        for (const agentPath of possiblePaths) {
            if (await fileManager.pathExists(agentPath)) {
                try {
                    const agentContent = await fileManager.readFile(agentPath);
                    const yamlMatch = agentContent.match(
                        /```ya?ml\r?\n([\s\S]*?)```/
                    );

                    if (yamlMatch) {
                        const yaml = yamlMatch[1];
                        const titleMatch = yaml.match(/title:\s*(.+)/);
                        if (titleMatch) {
                            return titleMatch[1].trim();
                        }
                    }
                } catch (error) {
                    console.warn(
                        `已存在 .roomodes 文件，包含 ${existingModes.length} 个模式`
                    );
                }
            }
        }

        // Fallback to formatted agent ID
        return agentId
            .split("-")
            .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
            .join(" ");
    }

    async getAllTaskIds(installDir) {
        const glob = require("glob");
        const allTaskIds = [];

        // Check core tasks in .sdat-core or root
        let tasksDir = path.join(installDir, ".sdat-core", "tasks");
        if (!(await fileManager.pathExists(tasksDir))) {
            tasksDir = path.join(installDir, "sdat-core", "tasks");
        }

        if (await fileManager.pathExists(tasksDir)) {
            const taskFiles = glob.sync("*.md", { cwd: tasksDir });
            allTaskIds.push(
                ...taskFiles.map((file) => path.basename(file, ".md"))
            );
        }

        // Check common tasks
        const commonTasksDir = path.join(installDir, "common", "tasks");
        if (await fileManager.pathExists(commonTasksDir)) {
            const commonTaskFiles = glob.sync("*.md", { cwd: commonTasksDir });
            allTaskIds.push(
                ...commonTaskFiles.map((file) => path.basename(file, ".md"))
            );
        }

        // Also check for expansion pack tasks in dot folders
        const expansionDirs = glob.sync(".*/tasks", { cwd: installDir });
        for (const expDir of expansionDirs) {
            const fullExpDir = path.join(installDir, expDir);
            const expTaskFiles = glob.sync("*.md", { cwd: fullExpDir });
            allTaskIds.push(
                ...expTaskFiles.map((file) => path.basename(file, ".md"))
            );
        }

        // Check expansion-packs folder tasks
        const expansionPacksDir = path.join(installDir, "expansion-packs");
        if (await fileManager.pathExists(expansionPacksDir)) {
            const expPackDirs = glob.sync("*/tasks", {
                cwd: expansionPacksDir,
            });
            for (const expDir of expPackDirs) {
                const fullExpDir = path.join(expansionPacksDir, expDir);
                const expTaskFiles = glob.sync("*.md", { cwd: fullExpDir });
                allTaskIds.push(
                    ...expTaskFiles.map((file) => path.basename(file, ".md"))
                );
            }
        }

        // Remove duplicates
        return [...new Set(allTaskIds)];
    }

    async findTaskPath(taskId, installDir) {
        // Try to find the task file in various locations
        const possiblePaths = [
            path.join(installDir, ".sdat-core", "tasks", `${taskId}.md`),
            path.join(installDir, "sdat-core", "tasks", `${taskId}.md`),
            path.join(installDir, "common", "tasks", `${taskId}.md`),
        ];

        // Also check expansion pack directories
        const glob = require("glob");

        // Check dot folder expansion packs
        const expansionDirs = glob.sync(".*/tasks", { cwd: installDir });
        for (const expDir of expansionDirs) {
            possiblePaths.push(path.join(installDir, expDir, `${taskId}.md`));
        }

        // Check expansion-packs folder
        const expansionPacksDir = path.join(installDir, "expansion-packs");
        if (await fileManager.pathExists(expansionPacksDir)) {
            const expPackDirs = glob.sync("*/tasks", {
                cwd: expansionPacksDir,
            });
            for (const expDir of expPackDirs) {
                possiblePaths.push(
                    path.join(expansionPacksDir, expDir, `${taskId}.md`)
                );
            }
        }

        for (const taskPath of possiblePaths) {
            if (await fileManager.pathExists(taskPath)) {
                return taskPath;
            }
        }

        return null;
    }

    async getCoreSlashPrefix(installDir) {
        try {
            const coreConfigPath = path.join(
                installDir,
                ".sdat-core",
                "core-config.yaml"
            );
            if (!(await fileManager.pathExists(coreConfigPath))) {
                // Try sdat-core directory
                const altConfigPath = path.join(
                    installDir,
                    "sdat-core",
                    "core-config.yaml"
                );
                if (await fileManager.pathExists(altConfigPath)) {
                    const configContent =
                        await fileManager.readFile(altConfigPath);
                    const config = yaml.load(configContent);
                    return config.slashPrefix || "SDAT";
                }
                return "SDAT"; // fallback
            }

            const configContent = await fileManager.readFile(coreConfigPath);
            const config = yaml.load(configContent);
            return config.slashPrefix || "SDAT";
        } catch (error) {
            console.warn(
                `已存在 .roomodes 文件，包含 ${existingModes.length} 个模式`
            );
            return "SDAT";
        }
    }

    async getInstalledExpansionPacks(installDir) {
        const expansionPacks = [];

        // Check for dot-prefixed expansion packs in install directory
        const glob = require("glob");
        const dotExpansions = glob.sync(".sdat-*", { cwd: installDir });

        for (const dotExpansion of dotExpansions) {
            if (dotExpansion !== ".sdat-core") {
                const packPath = path.join(installDir, dotExpansion);
                const packName = dotExpansion.substring(1); // remove the dot
                expansionPacks.push({
                    name: packName,
                    path: packPath,
                });
            }
        }

        // Check for expansion-packs directory style
        const expansionPacksDir = path.join(installDir, "expansion-packs");
        if (await fileManager.pathExists(expansionPacksDir)) {
            const packDirs = glob.sync("*", { cwd: expansionPacksDir });

            for (const packDir of packDirs) {
                const packPath = path.join(expansionPacksDir, packDir);
                if (
                    (await fileManager.pathExists(packPath)) &&
                    (await fileManager.pathExists(
                        path.join(packPath, "config.yaml")
                    ))
                ) {
                    expansionPacks.push({
                        name: packDir,
                        path: packPath,
                    });
                }
            }
        }

        return expansionPacks;
    }

    async getExpansionPackSlashPrefix(packPath) {
        try {
            const configPath = path.join(packPath, "config.yaml");
            if (await fileManager.pathExists(configPath)) {
                const configContent = await fileManager.readFile(configPath);
                const config = yaml.load(configContent);
                return config.slashPrefix || path.basename(packPath);
            }
        } catch (error) {
            console.warn(
                `已存在 .roomodes 文件，包含 ${existingModes.length} 个模式`
            );
        }

        return path.basename(packPath); // fallback to directory name
    }

    async getExpansionPackAgents(packPath) {
        const agentsDir = path.join(packPath, "agents");
        if (!(await fileManager.pathExists(agentsDir))) {
            return [];
        }

        try {
            const glob = require("glob");
            const agentFiles = glob.sync("*.md", { cwd: agentsDir });
            return agentFiles.map((file) => path.basename(file, ".md"));
        } catch (error) {
            console.warn(
                `已存在 .roomodes 文件，包含 ${existingModes.length} 个模式`
            );
            return [];
        }
    }

    async getExpansionPackTasks(packPath) {
        const tasksDir = path.join(packPath, "tasks");
        if (!(await fileManager.pathExists(tasksDir))) {
            return [];
        }

        try {
            const glob = require("glob");
            const taskFiles = glob.sync("*.md", { cwd: tasksDir });
            return taskFiles.map((file) => path.basename(file, ".md"));
        } catch (error) {
            console.warn(
                `已存在 .roomodes 文件，包含 ${existingModes.length} 个模式`
            );
            return [];
        }
    }

    async setupRoo(installDir, selectedAgent) {
        const agents = selectedAgent
            ? [selectedAgent]
            : await this.getAllAgentIds(installDir);

        // Check for existing .roomodes file in project root
        const roomodesPath = path.join(installDir, ".roomodes");
        let existingModes = [];
        let existingContent = "";

        if (await fileManager.pathExists(roomodesPath)) {
            existingContent = await fileManager.readFile(roomodesPath);
            // Parse existing modes to avoid duplicates
            const modeMatches = existingContent.matchAll(/- slug: ([\w-]+)/g);
            for (const match of modeMatches) {
                existingModes.push(match[1]);
            }
            console.log(
                chalk.yellow(
                    `已存在 .roomodes 文件，包含 ${existingModes.length} 个模式`
                )
            );
        }

        // Create new modes content
        let newModesContent = "";

        // Load dynamic agent permissions from configuration
        const config = await this.loadIdeAgentConfig();
        const agentPermissions = config["roo-permissions"] || {};

        for (const agentId of agents) {
            // Skip if already exists
            // Check both with and without sdat- prefix to handle both cases
            const checkSlug = agentId.startsWith("sdat-")
                ? agentId
                : `sdat-${agentId}`;
            if (existingModes.includes(checkSlug)) {
                console.log(chalk.dim(`已存在 ${agentId} - 已在 .roomodes 中`));
                continue;
            }

            // Read agent file to extract all information
            const agentPath = await this.findAgentPath(agentId, installDir);

            if (agentPath) {
                const agentContent = await fileManager.readFile(agentPath);

                // Extract YAML content
                const yamlMatch = agentContent.match(
                    /```ya?ml\r?\n([\s\S]*?)```/
                );
                if (yamlMatch) {
                    const yaml = yamlMatch[1];

                    // Extract agent info from YAML
                    const titleMatch = yaml.match(/title:\s*(.+)/);
                    const iconMatch = yaml.match(/icon:\s*(.+)/);
                    const whenToUseMatch = yaml.match(/whenToUse:\s*"(.+)"/);
                    const roleDefinitionMatch = yaml.match(
                        /roleDefinition:\s*"(.+)"/
                    );

                    const title = titleMatch
                        ? titleMatch[1].trim()
                        : await this.getAgentTitle(agentId, installDir);
                    const icon = iconMatch ? iconMatch[1].trim() : "🤖";
                    const whenToUse = whenToUseMatch
                        ? whenToUseMatch[1].trim()
                        : `用于 ${title} 相关任务`;
                    const roleDefinition = roleDefinitionMatch
                        ? roleDefinitionMatch[1].trim()
                        : `你是一名 ${title}，专注于 ${title.toLowerCase()} 相关的任务和职责。`;

                    // Build mode entry with proper formatting (matching exact indentation)
                    // Avoid double "sdat-" prefix for agents that already have it
                    const slug = agentId.startsWith("sdat-")
                        ? agentId
                        : `sdat-${agentId}`;
                    newModesContent += ` - slug: ${slug}\n`;
                    newModesContent += `   name: '${icon} ${title}'\n`;
                    newModesContent += `   roleDefinition: ${roleDefinition}\n`;
                    newModesContent += `   whenToUse: ${whenToUse}\n`;
                    // Get relative path from installDir to agent file
                    const relativePath = path
                        .relative(installDir, agentPath)
                        .replace(/\\/g, "/");
                    newModesContent += `   customInstructions: 关键信息：阅读完整的 YAML 内容，开始激活以改变你的状态，遵循启动部分的说明，保持此状态直到收到退出此模式的指令\n`;
                    newModesContent += `   groups:\n`;
                    newModesContent += `    - read\n`;

                    // Add permissions based on agent type
                    const permissions = agentPermissions[agentId];
                    if (permissions) {
                        newModesContent += `    - - edit\n`;
                        newModesContent += `      - fileRegex: ${permissions.fileRegex}\n`;
                        newModesContent += `        description: ${permissions.description}\n`;
                    } else {
                        newModesContent += `    - edit\n`;
                    }

                    console.log(
                        chalk.green(
                            `✓ 已添加模式: sdat-${agentId} (${icon} ${title})`
                        )
                    );
                }
            }
        }

        // Build final roomodes content
        let roomodesContent = "";
        if (existingContent) {
            // If there's existing content, append new modes to it
            roomodesContent = existingContent.trim() + "\n" + newModesContent;
        } else {
            // Create new .roomodes file with proper YAML structure
            roomodesContent = "customModes:\n" + newModesContent;
        }

        // Write .roomodes file
        await fileManager.writeFile(roomodesPath, roomodesContent);
        console.log(chalk.green("✓ 已创建 .roomodes 文件在项目根目录"));

        console.log(chalk.green(`\n✓ Roo Code 配置完成！`));
        console.log(
            chalk.dim("自定义模式将在你在 Roo Code 中打开此项目时可用")
        );

        return true;
    }

    async setupCline(installDir, selectedAgent) {
        const clineRulesDir = path.join(installDir, ".clinerules");
        const agents = selectedAgent
            ? [selectedAgent]
            : await this.getAllAgentIds(installDir);

        await fileManager.ensureDirectory(clineRulesDir);

        // Load dynamic agent ordering from configuration
        const config = await this.loadIdeAgentConfig();
        const agentOrder = config["cline-order"] || {};

        for (const agentId of agents) {
            // Find the agent file
            const agentPath = await this.findAgentPath(agentId, installDir);

            if (agentPath) {
                const agentContent = await fileManager.readFile(agentPath);

                // Get numeric prefix for ordering
                const order = agentOrder[agentId] || 99;
                const prefix = order.toString().padStart(2, "0");
                const mdPath = path.join(
                    clineRulesDir,
                    `${prefix}-${agentId}.md`
                );

                // Create MD content for Cline (focused on project standards and role)
                let mdContent = `# ${await this.getAgentTitle(agentId, installDir)} 智能体\n\n`;
                mdContent += `此规则定义了 ${await this.getAgentTitle(agentId, installDir)} 智能体的角色和项目标准。\n\n`;
                mdContent += "## 角色定义\n\n";
                mdContent +=
                    "当用户输入 `@" +
                    agentId +
                    "` 时，采用此角色并遵循以下指南：\n\n";
                mdContent += "```yaml\n";
                // Extract just the YAML content from the agent file
                const yamlContent = extractYamlFromAgent(agentContent);
                if (yamlContent) {
                    mdContent += yamlContent;
                } else {
                    // If no YAML found, include the whole content minus the header
                    mdContent += agentContent.replace(/^#.*$/m, "").trim();
                }
                mdContent += "\n```\n\n";
                mdContent += "## 项目标准\n\n";
                mdContent += `- 始终与 .sdat-core/ 中的项目文档保持一致\n`;
                mdContent += `- 遵循智能体的特定指南和约束\n`;
                mdContent += `- 当进行更改时，更新相关项目文件\n`;
                const relativePath = path
                    .relative(installDir, agentPath)
                    .replace(/\\/g, "/");
                mdContent += `- 参考完整的智能体定义在 [${relativePath}](${relativePath})\n\n`;
                mdContent += "## 用法\n\n";
                mdContent += `输入 \`@${agentId}\` 来激活此 ${await this.getAgentTitle(agentId, installDir)} 角色。\n`;

                await fileManager.writeFile(mdPath, mdContent);
                console.log(
                    chalk.green(`✓ 已创建规则: ${prefix}-${agentId}.md`)
                );
            }
        }

        console.log(chalk.green(`\n✓ 已创建 Cline 规则在 ${clineRulesDir}`));

        return true;
    }

    async setupGeminiCli(installDir) {
        const geminiDir = path.join(installDir, ".gemini");
        const sdatMethodDir = path.join(geminiDir, "sdat-method");
        await fileManager.ensureDirectory(sdatMethodDir);

        // Update logic for existing settings.json
        const settingsPath = path.join(geminiDir, "settings.json");
        if (await fileManager.pathExists(settingsPath)) {
            try {
                const settingsContent =
                    await fileManager.readFile(settingsPath);
                const settings = JSON.parse(settingsContent);
                let updated = false;

                // Handle contextFileName property
                if (
                    settings.contextFileName &&
                    Array.isArray(settings.contextFileName)
                ) {
                    const originalLength = settings.contextFileName.length;
                    settings.contextFileName = settings.contextFileName.filter(
                        (fileName) => !fileName.startsWith("agents/")
                    );
                    if (settings.contextFileName.length !== originalLength) {
                        updated = true;
                    }
                }

                if (updated) {
                    await fileManager.writeFile(
                        settingsPath,
                        JSON.stringify(settings, null, 2)
                    );
                    console.log(
                        chalk.green(
                            "✓ 已更新 .gemini/settings.json - 移除智能体文件引用"
                        )
                    );
                }
            } catch (error) {
                console.warn(
                    chalk.yellow("  警告：无法更新 .gemini/settings.json"),
                    error
                );
            }
        }

        // Remove old agents directory
        const agentsDir = path.join(geminiDir, "agents");
        if (await fileManager.pathExists(agentsDir)) {
            await fileManager.removeDirectory(agentsDir);
            console.log(chalk.green("✓ 已移除旧的 .gemini/agents 目录"));
        }

        // Get all available agents
        const agents = await this.getAllAgentIds(installDir);
        let concatenatedContent = "";

        for (const agentId of agents) {
            // Find the source agent file
            const agentPath = await this.findAgentPath(agentId, installDir);

            if (agentPath) {
                const agentContent = await fileManager.readFile(agentPath);

                // Create properly formatted agent rule content (similar to trae)
                let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
                agentRuleContent += `当用户输入 \`*${agentId}\` 时，激活 ${await this.getAgentTitle(
                    agentId,
                    installDir
                )} 代理角色。\n\n`;
                agentRuleContent += "## Agent Activation\n\n";
                agentRuleContent +=
                    "CRITICAL：阅读完整的 YAML 内容，开始激活以改变你的状态，遵循启动部分的说明，保持此状态直到收到退出此模式的指令：\n\n";
                agentRuleContent += "```yaml\n";
                // Extract just the YAML content from the agent file
                const yamlContent = extractYamlFromAgent(agentContent);
                if (yamlContent) {
                    agentRuleContent += yamlContent;
                } else {
                    // If no YAML found, include the whole content minus the header
                    agentRuleContent += agentContent
                        .replace(/^#.*$/m, "")
                        .trim();
                }
                agentRuleContent += "\n```\n\n";
                agentRuleContent += "## File Reference\n\n";
                const relativePath = path
                    .relative(installDir, agentPath)
                    .replace(/\\/g, "/");
                agentRuleContent += `完整的 ${agentId} 定义内容可在 [${relativePath}](${relativePath}) 中找到。\n\n`;
                agentRuleContent += "## Usage\n\n";
                agentRuleContent += `当用户输入 \`*${agentId}\` 时，激活 ${await this.getAgentTitle(
                    agentId,
                    installDir
                )} 代理角色并遵循 YAML 配置文件中定义的所有指令。\n`;

                // Add to concatenated content with separator
                concatenatedContent += agentRuleContent + "\n\n---\n\n";
                console.log(chalk.green(`✓ 已添加上下文 @${agentId}`));
            }
        }

        // Write the concatenated content to GEMINI.md
        const geminiMdPath = path.join(sdatMethodDir, "GEMINI.md");
        await fileManager.writeFile(geminiMdPath, concatenatedContent);
        console.log(chalk.green(`\n✓ 已创建 GEMINI.md 在 ${sdatMethodDir}`));

        return true;
    }

    async setupGitHubCopilot(
        installDir,
        selectedAgent,
        spinner = null,
        preConfiguredSettings = null
    ) {
        // Configure VS Code workspace settings first to avoid UI conflicts with loading spinners
        await this.configureVsCodeSettings(
            installDir,
            spinner,
            preConfiguredSettings
        );

        const chatmodesDir = path.join(installDir, ".github", "chatmodes");
        const agents = selectedAgent
            ? [selectedAgent]
            : await this.getAllAgentIds(installDir);

        await fileManager.ensureDirectory(chatmodesDir);

        for (const agentId of agents) {
            // Find the agent file
            const agentPath = await this.findAgentPath(agentId, installDir);
            const chatmodePath = path.join(
                chatmodesDir,
                `${agentId}.chatmode.md`
            );

            if (agentPath) {
                // Create chat mode file with agent content
                const agentContent = await fileManager.readFile(agentPath);
                const agentTitle = await this.getAgentTitle(
                    agentId,
                    installDir
                );

                // Extract whenToUse for the description
                const yamlMatch = agentContent.match(
                    /```ya?ml\r?\n([\s\S]*?)```/
                );
                let description = `激活 ${agentTitle} 智能体角色。`;
                if (yamlMatch) {
                    const whenToUseMatch =
                        yamlMatch[1].match(/whenToUse:\s*"(.*?)"/);
                    if (whenToUseMatch && whenToUseMatch[1]) {
                        description = whenToUseMatch[1];
                    }
                }

                let chatmodeContent = `---
description: "${description.replace(/"/g, '\\"')}"
tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems', 'usages', 'editFiles', 'runCommands', 'runTasks', 'runTests', 'search', 'searchResults', 'terminalLastCommand', 'terminalSelection', 'testFailure']
---

`;
                chatmodeContent += agentContent;

                await fileManager.writeFile(chatmodePath, chatmodeContent);
                console.log(
                    chalk.green(`✓ Created chat mode: ${agentId}.chatmode.md`)
                );
            }
        }

        console.log(chalk.green(`\n✓ 已完成 GitHub Copilot 设置!`));
        console.log(
            chalk.dim(`你现在可以在 Chat 视图的模式选择器中找到 SDAT Agent。`)
        );

        return true;
    }

    async configureVsCodeSettings(
        installDir,
        spinner,
        preConfiguredSettings = null
    ) {
        const vscodeDir = path.join(installDir, ".vscode");
        const settingsPath = path.join(vscodeDir, "settings.json");

        await fileManager.ensureDirectory(vscodeDir);

        // Read existing settings if they exist
        let existingSettings = {};
        if (await fileManager.pathExists(settingsPath)) {
            try {
                const existingContent =
                    await fileManager.readFile(settingsPath);
                existingSettings = JSON.parse(existingContent);
                console.log(
                    chalk.yellow(
                        "已找到现有的 .vscode/settings.json 文件。正在合并 SDAT 设置..."
                    )
                );
            } catch (error) {
                console.warn(
                    chalk.yellow(
                        "无法解析现有 settings.json 文件。正在创建新文件。"
                    )
                );
                existingSettings = {};
            }
        }

        // Use pre-configured settings if provided, otherwise prompt
        let configChoice;
        if (preConfiguredSettings && preConfiguredSettings.configChoice) {
            configChoice = preConfiguredSettings.configChoice;
            console.log(
                chalk.dim(
                    `正在使用预配置的 GitHub Copilot 设置: ${configChoice}`
                )
            );
        } else {
            // Clear any previous output and add spacing to avoid conflicts with loaders
            console.log("\n".repeat(2));
            console.log(chalk.blue("🔧 GitHub Copilot 智能体设置配置"));
            console.log(
                chalk.dim(
                    "SDAT 最佳工作配置需要特定的 VS Code 设置，以获得最佳的代理体验。"
                )
            );
            console.log(""); // Add extra spacing

            const response = await inquirer.prompt([
                {
                    type: "list",
                    name: "configChoice",
                    message: chalk.yellow(
                        "你希望如何配置 GitHub Copilot 设置？"
                    ),
                    choices: [
                        {
                            name: "使用推荐默认值（最快设置）",
                            value: "defaults",
                        },
                        {
                            name: "手动配置每个设置（根据你的偏好自定义）",
                            value: "manual",
                        },
                        {
                            name: "跳过设置配置（稍后手动配置）",
                            value: "skip",
                        },
                    ],
                    default: "defaults",
                },
            ]);
            configChoice = response.configChoice;
        }

        let sdatSettings = {};

        if (configChoice === "skip") {
            console.log(chalk.yellow("⚠️  已跳过 VS Code 设置配置。"));
            console.log(
                chalk.dim(
                    "你可以在 .vscode/settings.json 文件中手动配置这些设置："
                )
            );
            console.log(chalk.dim("  • chat.agent.enabled: true"));
            console.log(chalk.dim("  • chat.agent.maxRequests: 15"));
            console.log(
                chalk.dim("  • github.copilot.chat.agent.runTasks: true")
            );
            console.log(chalk.dim("  • chat.mcp.discovery.enabled: true"));
            console.log(
                chalk.dim("  • github.copilot.chat.agent.autoFix: true")
            );
            console.log(chalk.dim("  • chat.tools.autoApprove: false"));
            return true;
        }

        if (configChoice === "defaults") {
            // Use recommended defaults
            sdatSettings = {
                "chat.agent.enabled": true,
                "chat.agent.maxRequests": 15,
                "github.copilot.chat.agent.runTasks": true,
                "chat.mcp.discovery.enabled": true,
                "github.copilot.chat.agent.autoFix": true,
                "chat.tools.autoApprove": false,
            };
            console.log(
                chalk.green(
                    "✓ 已使用推荐的 SDAT 默认值配置 GitHub Copilot 设置"
                )
            );
        } else {
            // Manual configuration
            console.log(chalk.blue("\n📋 让我们为你的偏好配置每个设置："));

            // Pause spinner during manual configuration prompts
            let spinnerWasActive = false;
            if (spinner && spinner.isSpinning) {
                spinner.stop();
                spinnerWasActive = true;
            }

            const manualSettings = await inquirer.prompt([
                {
                    type: "input",
                    name: "maxRequests",
                    message: "每个代理会话的最大请求数（推荐：15）？",
                    default: "15",
                    validate: (input) => {
                        const num = parseInt(input);
                        if (isNaN(num) || num < 1 || num > 50) {
                            return "请输入 1 到 50 之间的数字";
                        }
                        return true;
                    },
                },
                {
                    type: "confirm",
                    name: "runTasks",
                    message:
                        "是否允许代理运行工作区任务（package.json 脚本等）？",
                    default: true,
                },
                {
                    type: "confirm",
                    name: "mcpDiscovery",
                    message: "是否启用 MCP（模型上下文协议）服务器发现？",
                    default: true,
                },
                {
                    type: "confirm",
                    name: "autoFix",
                    message: "是否启用自动错误检测和修复生成的代码？",
                    default: true,
                },
                {
                    type: "confirm",
                    name: "autoApprove",
                    message:
                        "是否自动批准所有工具而无需确认？（⚠️  实验性 - 安全性较低）",
                    default: false,
                },
            ]);

            // Restart spinner if it was active before prompts
            if (spinner && spinnerWasActive) {
                spinner.start();
            }

            sdatSettings = {
                "chat.agent.enabled": true, // Always enabled - required for SDAT agents
                "chat.agent.maxRequests": parseInt(manualSettings.maxRequests),
                "github.copilot.chat.agent.runTasks": manualSettings.runTasks,
                "chat.mcp.discovery.enabled": manualSettings.mcpDiscovery,
                "github.copilot.chat.agent.autoFix": manualSettings.autoFix,
                "chat.tools.autoApprove": manualSettings.autoApprove,
            };

            console.log(chalk.green("✓ 已手动配置自定义设置"));
        }

        // Merge settings (existing settings take precedence to avoid overriding user preferences)
        const mergedSettings = { ...sdatSettings, ...existingSettings };

        // Write the updated settings
        await fileManager.writeFile(
            settingsPath,
            JSON.stringify(mergedSettings, null, 2)
        );

        console.log(chalk.green("✓ 已成功配置 VS Code 工作区设置"));
        console.log(chalk.dim("  设置已写入 .vscode/settings.json："));
        Object.entries(sdatSettings).forEach(([key, value]) => {
            console.log(chalk.dim(`  • ${key}: ${value}`));
        });
        console.log(chalk.dim(""));
        console.log(
            chalk.dim("你可以随时在 .vscode/settings.json 文件中修改这些设置")
        );
    }
}

module.exports = new IdeSetup();
